//
//  ZYSecurityPolicy.h
//  ZYWebImage
//
//  Created by wangzhipan on 2025/4/11.
//

#import <Foundation/Foundation.h>

/*
 https 就是http+ssl\tsl
 
 ssl流程：
 
 1、首先客户端发送client hello报文，将客户端支持的ssl\tls版本、加密套件发给服务器
 
 2、服务器回应server hello报文，将服务器支持的的ssl\tls版本、选中的加密组件【包含加密算法、秘钥长度等】发给客户端
 
 3、服务器再发生证书【Certificate】报文，包含公开秘钥证书、加密公钥、证书颁发机构\日志等信息
 
 4、服务器最后发生server hello done给客户端，表示第一阶段 ssl 协商部分结束
 
 5、客户端收到服务的2\3\4步信息，验证证书是否合法【日期、公钥、颁发机构、域名等信息】，不合法则断开连接，合法则：
 
        发送client key exchange报文，包含客户端的随机密码串，这个密码串有以下信息：
                首先它是一个随机序列号A
                a、使用服务器的公钥加密随机序列号A，成为一条消息B
                b、用类似md5  hash算法对 消息B 用 密匙随机序列号A 进行加密导出信息摘要信息C
                c、最后将消息B 与 摘要信息C 一起发给服务器
 
    客户端再发送Change Cipher Spec报文，通知服务器次数使用共享的秘钥加密，也就是 随机序列号A
 
 6、服务器收到客户端发送的信息：
        a、首先使用私钥解密消息B，得到客户端的随机序列号A
        b、使用随机序列号A 对 消息B 进行hash算法 获取摘要信息D
        c、对比摘要信息C和D，验证的到的校验值是否一致。如果一致则说明消息未被篡改，可以信任。
    到这里，server端解密就没问题了
 
 7、服务器根据非对称算法解密得到的随机序列号A，再用第2步中选中的加密算法来加密一段握手报文，然后用hash算法生成摘要信息，发给客户端
 
 8、客户端收到后：
        1、计算HASH值是否与发的消息一致
        2、检查消息是否为握手消息
 
 9、握手结束后，客户端和服务器端使用握手阶段产生的随机数以及挑选出来的算法进行对称加解密的传输


 
 总结来说，网络库里面需要做的事情，就是对服务器发过来的证书\公钥等信息进行验证，其他校对流程CFNetwork底层做了
 */

typedef NS_ENUM(NSInteger, ZYSSLPinningMode) {
    ZYSSLPinningModeNone,
    ZYSSLPinningModePublicKey,
    ZYSSLPinningModeCertificate
};

NS_ASSUME_NONNULL_BEGIN

@interface ZYSecurityPolicy : NSObject

//服务器信任应该根据固定的SSL证书进行评估的标准。默认值为 AFSSLPinningModeNone 。
@property (nonatomic, assign) ZYSSLPinningMode SSLPinningMode;

/*本地工程里面的证书，将与服务器证书进行验证
 Note that if pinning is enabled, `evaluateServerTrust:forDomain:` will return true if any pinned certificate matches.
 */
@property (nonatomic, strong, nullable) NSSet <NSData *> *pinnedCertificates;

//是否信任具有无效或过期SSL证书的服务器。默认值为 NO 。
@property (nonatomic, assign) BOOL allowInvalidCertificates;

//是否验证域名
@property (nonatomic, assign) BOOL validatesDomainName;


//返回包含在bundle中的任何证书
+ (NSSet <NSData *> *)certificatesInBundle:(NSBundle *)bundle;

+ (instancetype)defaultPolicy;

+ (instancetype)policyWithSSLPinningMode:(ZYSSLPinningMode)SSLPinningMode;

+ (instancetype)policyWithSSLPinningMode:(ZYSSLPinningMode)SSLPinningMode
                  withPinnedCertificates:(NSSet <NSData *> *)pinnedCertificates;

- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust
                  forDomain:(nullable NSString *)domain;
@end

NS_ASSUME_NONNULL_END
